package priv.pfz.basedao.mybatis;

import com.google.common.collect.ImmutableSet;
import priv.pfz.basedao.apt.AptUtils;
import priv.pfz.basedao.info.AbstractDaoInfoParser;
import priv.pfz.basedao.info.DaoInfo;
import priv.pfz.basedao.mybatis.mapper.DefaultBaseMapper;
import priv.pfz.basedao.mybatis.mapper.DefaultShardingBaseMapper;
import priv.pfz.basedao.mybatis.mapper.SimpleBaseMapper;
import priv.pfz.basedao.mybatis.mapper.SimpleShardingBaseMapper;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yyjxp
 * 2024/1/31 14:45
 */
public class DaoInfoCache extends AbstractDaoInfoParser {
    /**
     * dao信息缓存，各mapper在首次使用时解析并被缓存起来
     */
    private static final Map<Class<?>, DaoInfo> DAO_INFO_MAP = new ConcurrentHashMap<>();
    private static final DaoInfoCache INSTANCE = new DaoInfoCache();

    private static final Set<Type> BASE_MAPPER_CLASSES = ImmutableSet.of(
            SimpleBaseMapper.class,
            DefaultBaseMapper.class,
            SimpleShardingBaseMapper.class,
            DefaultShardingBaseMapper.class
    );

    public static DaoInfo getDaoInfo(Class<?> daoClass) {
        return DAO_INFO_MAP.computeIfAbsent(daoClass, k -> INSTANCE.parseDaoInfo(daoClass));
    }

    @Override
    protected String getDefaultTableName(Class<?> daoClass) {
        return AptUtils.classToTable(daoClass.getSimpleName().replace("Mapper", ""));
    }

    @Override
    protected Class<?> getEntityClass(Class<?> daoClass) {
        Type[] genericInterfaces = daoClass.getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType gi = (ParameterizedType) genericInterface;
                if (BASE_MAPPER_CLASSES.contains(gi.getRawType())) {
                    return (Class<?>) gi.getActualTypeArguments()[0];
                }
            }
        }
        throw new RuntimeException(MessageFormat.format("解析Mapper类{0}异常", daoClass.getSimpleName()));
    }
}
